from .apis import DingAPI
import httpx
from .access_token import DingAccessTokenManager
from .models import CalendarStartModel, CalendarEndModel, \
    CalendarCreateInputModel, CalendarQueryInputModel, CalendarDeleteInputModel, \
    CalendarModel, CalendarModifyInputModel, TodoModel, TodoCreateInputModel, TodoQueryInputModel, \
    TodoModifyInputModel, TodoDeleteInputModel
from utils.zlredis import ZLRedis


class ZLDingClient:
    def __init__(self):
        self.token_manager = DingAccessTokenManager()
        self._async_http = httpx.AsyncClient()
        self.zlredis = ZLRedis()

    @property
    def async_http(self):
        accesstoken = self.token_manager.access_token
        self._async_http.headers.update({"x-acs-dingtalk-access-token": accesstoken})
        return self._async_http

    async def _get_union_id(self, sender_staff_id: str):
        user_info = await self.get_user_info(sender_staff_id)
        print("userinfo::::", user_info)
        union_id = user_info['unionid']
        return union_id

    async def _get_user_info_from_ding(self, sender_staff_id: str):
        """
        从钉钉服务器获取钉钉用户信息
        :param sender_staff_id: 发送消息的员工id
        :return: 员工的信息
        """
        params = {"access_token": self.token_manager.access_token}
        data = {"language": "zh_CN", "userid": sender_staff_id}
        url = DingAPI.build_user_info_url()
        response = await self.async_http.post(url=url, json=data, params=params)
        response.raise_for_status()
        result = response.json().get('result')
        return result

    async def get_user_info(self, sender_staff_id: str):
        """
        根据发送消息的员工从缓存获取钉钉用户信息
        :param sender_staff_id: 发送消息的员工id
        :return:员工的信息
        """
        user_info = await self.zlredis.get_user(sender_staff_id)
        if not user_info:
            user_info = await self._get_user_info_from_ding(sender_staff_id)
            await self.zlredis.set_user(sender_staff_id=sender_staff_id, user_info=user_info)
            return user_info

    async def create_calendar(self, params: CalendarCreateInputModel):
        """
        build_create_calendar_url
        创建日程安排
        :param params:  创建日程的参数类型为CalendarModel
        :return:            钉钉服务器的返回值
        """
        union_id = await self._get_union_id(params.sender_staff_id)
        url = DingAPI.build_create_calendar_url(union_id)
        data = params.model_dump()
        response = await self.async_http.post(url=url, json=data)
        response.raise_for_status()
        return response.json()

    async def query_calendars(self, params: CalendarQueryInputModel):
        """
        查询指定时间段内的日程安排
        :param params: 查询日程所需的参数，类型为CalendarQueryInputModel
        :return: 从钉钉服务器上搜索到的指定时间段的日程
        """
        union_id = await self._get_union_id(params.sender_staff_id)
        url = DingAPI.build_query_calendar_url(union_id)
        params = params.model_dump()
        response = await self.async_http.get(url=url, params=params)
        response.raise_for_status()
        return response.json()['events']

    async def delete_calendar(self, params: CalendarDeleteInputModel):
        """
        删除指定id的日程
        :param params: 删除指定id日程所需的参数，类型为CalendarDeleteInputModel
        :return: 删除的结果
        """
        union_id = await self._get_union_id(params.sender_staff_id)
        url = DingAPI.build_delete_calendar_url(union_id=union_id, calendar_id=params.calendar_id)
        params = params.model_dump()
        response = await self.async_http.delete(url=url, params=params)
        return response.json()

    async def modify_calender(self, params: CalendarModifyInputModel):
        """
        修改日程安排
        :param 修改日程安排的参数CalendarModifyInputModel是参数的类型
        :return: 修改后的日程信息
        """
        union_id = await self._get_union_id(params.sender_staff_id)
        url = DingAPI.build_modify_calendar_url(union_id=union_id, calendar_id=params.calendar_id)
        data = params.model_dump()['calendar']
        data['id'] = params.calendar_id
        response = await self.async_http.put(url=url, json=data)
        return response.json()

#待办事项接口

    async def create_todo(self, params:TodoCreateInputModel):
        """
        创建待办事项
        :param params:创建待办事项需要的参数 TodoCreateInputModel是参数的类型
        :return: 创建待办事项的返回信息
        """
        union_id = await self._get_union_id(params.sender_staff_id)
        params_dict = params.model_dump()
        params_dict['executorIds'] = [union_id]
        params_dict['detailUrl'] = {
            "appUrl": "",
            "pcUrl": ""
        }
        url=DingAPI.build_create_todo_url(union_id=union_id)
        result = await self.async_http.post(url=url,json=params_dict)
        return result.json()

    async def query_todo(self, params: TodoQueryInputModel):
        """
        查询待办事项
        :param params: 查询待办事项的参数TodoQueryInputModel是参数的类型
        :return: 查询待办事项的返回值
        """
        union_id = await self._get_union_id(params.sender_staff_id)
        url = DingAPI.build_query_todo_url(union_id)
        data = {
            "isDone": False,
            "roleTypes": [["executor"], ["creator"],["participant"]]
        }

        result = await self.async_http.get(url=url,params=data)
        return result.json()


    async def modify_todo(self, params: TodoModifyInputModel):
        """
        修改待办事项
        :param params: 修改待办事项的参数TodoModifyInputModel是参数的类型
        :return: 修改待办事项的返回值
        """
        union_id = await self._get_union_id(params.sender_staff_id)
        url = DingAPI.build_update_todo_url(union_id=union_id,todo_id=params.todo_id)
        data = params.model_dump()
        response = await self.async_http.put(url=url,json=data)
        return response.json()

    async def delete_todo(self, params: TodoDeleteInputModel):
        """
        删除待办事项
        :param params: 删除待办事项的参数TodoDeleteInputModel是参数的类型
        :return: 删除待办事项的返回值
        """
        union_id = await self._get_union_id(params.sender_staff_id)
        url = DingAPI.build_delete_todo_url(union_id=union_id,todo_id=params.todo_id)
        response = await self.async_http.delete(url=url)
        return response.json()




